
'use strict'

const request = require('request')

const reqMethod = async (opt, ctx, method, token) => {
    opt = opt || {}
    if (!opt.url) {
        throw new Error({
            statusCode: 403,
            message: 'url is required.'
        })
    }
    opt.method = method
    opt.timeout = opt.timeout || 10e5
    if (token) {
        opt.headers = Object.assign({}, opt.headers, ctx.headers, {Authorization: token})
    }
    if (opt.headers) {
        delete opt.headers['content-length']
    }

    if (opt.form) {
        if (!opt.headers) {
            opt.headers = {}
        }
        opt.headers['Content-type'] = 'application/json'
        opt.body = opt.form
        opt.json = true
        delete opt.form
    }

    return new Promise((resolve, reject) => {
        request(opt, (err, res, body) => {
            if (err) {
                console.log(err)
                return reject({
                    statusCode: 500,
                    message: err
                })
            }
            if (res.statusCode !== 200) {
                return reject({
                    statusCode: res.statusCode,
                    message: `http code ${res.statusCode}`
                })
            }
            if (opt.encoding && (Buffer.isBuffer(body) || typeof(body) == 'string')) {
                return resolve(new Buffer(body, opt.encoding))
            }
	
            return resolve(typeof body === 'string' ? JSON.parse(body) : body)
        })
    })
}

const GetreqMethod = async (opt, ctx, method, token) => {
    opt = opt || {}
    if (!opt.url) {
        throw new Error({
            statusCode: 403,
            message: 'url is required.'
        })
    }
    opt.method = method
    opt.timeout = opt.timeout || 10e5
    if (token) {
        opt.headers = Object.assign({}, opt.headers, ctx.headers, {Authorization: token})
    }
    if (opt.headers) {
        delete opt.headers['content-length']
    }

    if (opt.form) {
        if (!opt.headers) {
            opt.headers = {}
        }
        opt.headers['Content-type'] = 'application/json'
        opt.body = opt.form
        opt.json = true
        delete opt.form
    }

    return new Promise((resolve, reject) => {
        request(opt, (err, res, body) => {
            if (err) {
                console.log(err)
                return reject({
                    statusCode: 500,
                    message: err
                })
            }
            if (res.statusCode !== 200) {
                return reject({
                    statusCode: res.statusCode,
                    message: `http code ${res.statusCode}`
                })
            }
            const arr = {
            	data:new Buffer(body, opt.encoding),
            	name:res.headers['content-disposition'].split('=')[1]
            }
            
            if (opt.encoding) {
                return resolve(arr)
            }
            
           return resolve(typeof body === 'string' ? JSON.parse(body) : body)
        })
    })
}

module.exports = {
    post: async (opt, ctx, method = 'post') => {
        try {
            const bodyOrQuery = method.toLowerCase() === 'get' ? 'query' : 'body'
            let bodyToken = ctx.request[bodyOrQuery].token || ctx.request[bodyOrQuery].xc_token || ctx.request[bodyOrQuery].login_token
            bodyToken = bodyToken ? `Bearer ${bodyToken}` : (ctx.headers.Authorization || ctx.headers.authorization)
            return await reqMethod(opt, ctx, 'post', bodyToken)
        } catch (e) {
            throw new Error(e)
        }
    },
    get: async (opt, ctx = {session: {}}, method = 'get') => {
        try {
            const bodyOrQuery = method.toLowerCase() === 'get' ? 'query' : 'body'
            let bodyToken = ctx.request[bodyOrQuery].token || ctx.request[bodyOrQuery].xc_token || ctx.request[bodyOrQuery].login_token
            bodyToken = bodyToken ? `Bearer ${bodyToken}` : (ctx.headers.Authorization || ctx.headers.authorization)

            return await reqMethod(opt, ctx, 'get', bodyToken)
        } catch (e) {
            throw new Error(e)
        }
    },
    getFile: async (opt, ctx = {session: {}}, method = 'get') => {
        try {
            const bodyOrQuery = method.toLowerCase() === 'get' ? 'query' : 'body'
            let bodyToken = ctx.request[bodyOrQuery].token || ctx.request[bodyOrQuery].xc_token || ctx.request[bodyOrQuery].login_token
            bodyToken = bodyToken ? `Bearer ${bodyToken}` : (ctx.headers.Authorization || ctx.headers.authorization)

            return await GetreqMethod(opt, ctx, 'get', bodyToken)
        } catch (e) {
            throw new Error(e)
        }
    }
}

